<template>
  <el-form
    :model="dataSourceForm"
    label-width="auto"
    size="medium"
    :rules="dataSourceFormRule"
    ref="EvForm"
    @submit.native.prevent
  >
    <el-row>
      <el-col :span="item.span ? item.span : calcSpan" v-for="(item, index) in dataSourceFormItems" :key="index">
        <el-form-item
          :label="tanslate(item.label)"
          :prop="item.model"
          :style="mergedItemStyle"
          :labelWidth="autoWidth ? 'auto' : fixedLabelWidth"
        >
          <template v-if="item.type === 'input'">
            <el-input
              v-if="item.inputType === 'number'"
              v-model.number="dataSourceForm[item.model]"
              :placeholder="placeholder(item.label, item.type)"
              clearable
              :disabled="isItemDisabled(item)"
              @change="item.change ? item.change($event) : () => {}"
              @keyup.enter.native="item.enter ? item.enter($event) : () => {}"
              v-bind="item.bind"
            />
            <el-input
              v-else
              :value="getValue(item.model)"
              @input="setValue(item.model, $event)"
              :placeholder="placeholder(item.label, item.type)"
              clearable
              :disabled="isItemDisabled(item)"
              @change="item.change ? item.change($event) : $emit('autoEmit', item.model, $event)"
              @keyup.enter.native="item.enter ? item.enter($event) : () => {}"
              v-bind="item.bind"
            />
          </template>
          <template v-if="item.type === 'select'">
            <el-select
              v-model="dataSourceForm[item.model]"
              :placeholder="placeholder(item.label, item.type)"
              style="width: 100%"
              clearable
              :filterable="item.filterable"
              :multiple="item.multiple"
              :disabled="isItemDisabled(item)"
              @change="item.change ? item.change($event) : () => {}"
              v-bind="item.bind"
            >
              <el-option
                v-for="(option, optionIndex) in item.options"
                :key="optionIndex"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
          </template>
          <template v-if="item.type === 'formSelect'">
            <FormSelectAuto
              v-model="dataSourceForm[item.model]"
              :placeholder="placeholder(item.label, item.type)"
              :columns="item.columns"
              :fieldLabel="item.fieldLabel"
              :fieldValue="item.fieldValue"
              :fieldLock="item.fieldLock"
              ref="FormSelectAuto"
              v-if="item.auto"
              v-bind="item.bind"
              v-on="item.on"
              @optionSet="
                (data) => {
                  item.options = data;
                }
              "
            />
            <FormSelectManual
              v-model="dataSourceForm[item.model]"
              :columns="item.columns"
              :placeholder="placeholder(item.label, item.type)"
              :fieldLabel="item.fieldLabel"
              :fieldValue="item.fieldValue"
              :fieldLock="item.fieldLock"
              ref="FormSelectManual"
              v-if="!item.auto"
              v-bind="item.bind"
              v-on="item.on"
              :disabled="isItemDisabled(item)"
              @optionSet="
                (data) => {
                  item.options = data;
                }
              "
            />
          </template>
          <template v-if="item.type === 'formSelects'">
            <FormSelectsAuto
              v-model="dataSourceForm[item.model]"
              :placeholder="placeholder(item.label, item.type)"
              :columns="item.columns"
              :fieldLabel="item.fieldLabel"
              :fieldValue="item.fieldValue"
              :fieldLock="item.fieldLock"
              ref="formSelectsAuto"
              v-if="item.auto"
              v-bind="item.bind"
              v-on="item.on"
              @optionSet="
                (data) => {
                  item.options = data;
                }
              "
            />
            <FormSelectsManual
              v-model="dataSourceForm[item.model]"
              :placeholder="placeholder(item.label, item.type)"
              :columns="item.columns"
              :fieldLabel="item.fieldLabel"
              :fieldValue="item.fieldValue"
              :fieldLock="item.fieldLock"
              ref="formSelectsManual"
              v-else
              v-bind="item.bind"
              v-on="item.on"
              @optionSet="
                (data) => {
                  item.options = data;
                }
              "
            />
          </template>
          <template v-if="item.type === 'date'">
            <el-date-picker
              v-model="dataSourceForm[item.model]"
              :type="item.dateType"
              :disabled="isItemDisabled(item)"
              style="width: 100%; display: inline-flex"
              unlink-panels
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              @change="item.change ? item.change($event) : () => {}"
              v-bind="item.bind"
            />
          </template>
          <template v-if="item.type === 'switch'">
            <el-switch
              v-model="dataSourceForm[item.model]"
              active-color="#48c365"
              inactive-color="#dadde5"
              :active-text="tanslate(item.activeText)"
              :inactive-text="tanslate(item.inactiveText)"
              :active-value="item.activeValue"
              :inactive-value="item.inactiveValue"
              @change="item.change ? item.change($event) : () => {}"
              v-bind="item.bind"
            />
          </template>
          <template v-if="item.type === 'textarea'">
            <el-input
              type="textarea"
              :rows="item.rows ? item.rows : 2"
              :placeholder="placeholder(item.label, item.type)"
              v-model="dataSourceForm[item.model]"
              :disabled="item.disabled"
              v-bind="item.bind"
            />
          </template>
          <template v-else-if="item.type === 'checkbox'">
            <el-checkbox-group v-model="dataSourceForm[item.model]" v-bind="item.bind" v-on="item.on">
              <el-checkbox
                v-for="(option, index) in item.options"
                :key="index"
                :label="option.value"
                :disabled="option.disabled"
              >
                {{ option.label }}
              </el-checkbox>
            </el-checkbox-group>
          </template>
          <template v-else-if="item.type === 'radio'">
            <el-radio-group v-model="dataSourceForm[item.model]" v-bind="item.bindGroup" v-on="item.on">
              <el-radio
                v-for="(option, index) in item.options"
                :key="index"
                :label="option.value"
                :disabled="option.disabled"
                v-bind="item.bindEvery"
              >
                {{ option.label }}
              </el-radio>
            </el-radio-group>
          </template>
          <template v-else-if="item.slot">
            <slot :name="item.slot" :scope="dataSourceForm" />
          </template>
        </el-form-item>
      </el-col>
    </el-row>
    <slot
      name="custom"
      :dataSourceForm="dataSourceForm"
      :dataSourceFormItems="dataSourceFormItems"
      :dataSourceFormRule="dataSourceFormRule"
    ></slot>
  </el-form>
</template>

<script>
import FormSelectAuto from "./formSelectAutoPage.vue";
import FormSelectManual from "./formSelectManualPage.vue";
import FormSelectsManual from "./formSelectsManualPage.vue";
import FormSelectsAuto from "./formSelectsAutoPage.vue";
export default {
  components: { FormSelectAuto, FormSelectManual, FormSelectsManual, FormSelectsAuto },
  props: {
    dataSourceFormOptions: {
      type: Object,
      default: () => {
        return {};
      },
    },
    colomnCount: {
      type: Number,
      default: 3,
    },
    monitoring: {
      type: Boolean,
      default: false,
    },
    readOnly: {
      type: Boolean,
      default: false,
    },
    itemStyle: {
      type: Object,
      default: () => ({}),
    },
    dialogVisible: {
      type: Boolean,
    },
    autoWidth: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      defaultStyle: {
        marginRight: "1%",
        marginBottom: "20px",
      },
    };
  },
  computed: {
    dataSourceForm() {
      return this.dataSourceFormOptions.dataSourceForm || {};
    },
    dataSourceFormItems() {
      return this.dataSourceFormOptions.dataSourceFormItems || [];
    },
    dataSourceFormRule() {
      return this.dataSourceFormOptions.dataSourceFormRule || {};
    },
    calcSpan() {
      return Math.floor(24 / this.colomnCount);
    },
    mergedItemStyle() {
      return { ...this.defaultStyle, ...this.itemStyle };
    },
    templates() {
      let result = [];
      this.dataSourceFormItems.forEach((formItem) => {
        if (formItem.slots) {
          let slotsList = Object.values(formItem.slots);
          slotsList.forEach((slot) => {
            if (result.indexOf(slot) === -1) {
              result.push(slot);
            }
          });
        }
      });
      return result;
    },
    fixedLabelWidth() {
      const minWidth = 80;
      // 根据中英文字符的宽度计算固定的 label 宽度
      let chineseWidth = 20; // 中文字符宽度
      let englishWidth = 9; // 英文字符宽度
      let maxWidth = 0;

      // 遍历表单项，找出最长的 label
      this.dataSourceFormItems.forEach((item) => {
        const label = this.tanslate(item.label);
        let labelWidth = 0;
        for (let i = 0; i < label.length; i++) {
          let charCode = label.charCodeAt(i);
          labelWidth += charCode >= 0x4e00 && charCode <= 0x9fa5 ? chineseWidth : englishWidth;
        }
        maxWidth = Math.max(maxWidth, labelWidth);
      });

      // 最终 label 宽度为最长 label 的宽度或者最小宽度的较大值
      return `${Math.max(minWidth, maxWidth)}px`;
    },
  },
  mounted() {
    if (this.monitoring) {
      this.startOptionChangeMonitoring();
    }
  },
  beforeDestroy() {
    // 遍历所有父组件
    this.$parent.$children.forEach((child) => {
      // 判断是否为当前组件实例的父组件
      if ("EvForm" in child.$refs) {
        // 调用子组件的 resetFields 方法
        child.$refs.EvForm.resetFields();
      }
    });
  },

  methods: {
    placeholder(label, type) {
      const placeholderfix = this.$t(label);
      if (type === "input") {
        return this.$t("common.please_input") + placeholderfix;
      } else {
        return this.$t("common.please_select") + placeholderfix;
      }
    },
    tanslate(label) {
      return this.$t(label);
    },
    resetFormData() {
      Object.keys(this.dataSourceForm).forEach((key) => {
        this.dataSourceForm[key] = "";
      });
    },
    getValueFromObject(obj, path) {
      const keys = path.split(".");
      let value = obj;
      for (const key of keys) {
        if (value && typeof value === "object") {
          value = value[key];
        } else {
          value = undefined;
          break;
        }
      }
      return value;
    },
    getValue(path) {
      // 通过路径获取对应的值
      const value = path.split(".").reduce((obj, key) => {
        return obj[key];
      }, this.dataSourceForm);
      return value !== undefined ? value : null; // 如果值是 undefined，返回 null
    },
    setValue(path, value) {
      // 通过路径设置对应的值
      const keys = path.split(".");
      const lastKey = keys.pop();
      let obj = keys.reduce((obj, key) => obj[key], this.dataSourceForm);
      obj[lastKey] = value;
    },
    isItemDisabled(item) {
      return this.readOnly || item.disabled;
    },
    optionsDeal(optionsName, options) {
      const item = this.findFormItem(optionsName);
      if (item) {
        item.options = options;
      }
    },
    optionsClean(optionsNames) {
      const names = Array.isArray(optionsNames) ? optionsNames : [optionsNames];
      names.forEach((name) => {
        const item = this.findFormItem(name);
        if (item) {
          item.options = [];
        }
      });
    },
    resetFields() {
      this.$refs.EvForm.resetFields();
    },
    validate() {
      return this.$refs.EvForm.validate();
    },
    startOptionChangeMonitoring() {
      const relations = {};
      const locks = {};
      this.dataSourceFormItems.forEach((item) => {
        if (item.relation) {
          relations[item.model] = item.relation;
        }
        if (item.lock) {
          locks[item.model] = item.lock;
        }
      });

      for (const lockField of Object.values(locks)) {
        this.lockField(lockField);
      }

      for (const [key, relatedFields] of Object.entries(relations)) {
        this.setupFieldWatcher(key, relatedFields, locks);
      }
    },
    setupFieldWatcher(key, relatedFields, locks) {
      this.$watch(`dataSourceForm.${key}`, (newValue, oldValue) => {
        if (newValue !== oldValue) {
          if (!newValue) {
            this.handleRelationFieldsCleanup(relatedFields);
          }
          if (newValue && locks[key]) {
            this.unlockField(locks[key]);
          } else {
            this.lockField(locks[key]);
          }
        }
      });
    },
    handleRelationFieldsCleanup(relationFields) {
      relationFields.forEach((field) => {
        this.dataSourceForm[field] = "";
      });
    },
    lockField(lockField) {
      const item = this.findFormItem(lockField);
      if (item) {
        item.disabled = true;
      }
    },
    unlockField(lockField) {
      const item = this.findFormItem(lockField);
      if (item) {
        item.disabled = false;
      }
    },
    lockFields(fieldModels) {
      fieldModels.forEach((model) => {
        const item = this.findFormItem(model);
        if (item) {
          item.disabled = true;
        }
      });
    },
    // 批量解锁字段
    unlockFields(fieldModels) {
      fieldModels.forEach((model) => {
        const item = this.findFormItem(model);
        if (item) {
          item.disabled = false;
        }
      });
    },
    findFormItem(model) {
      return this.dataSourceFormItems.find((item) => item.model === model);
    },
    getFormItemLabel(model, findObject) {
      const formItem = this.findFormItem(model);
      if (findObject && findObject[model]) {
        const foundItem = formItem.options.find((item) => item.value === findObject[model]);
        if (foundItem) {
          return foundItem.label;
        }
      }
      // 如果没有传递 findObject 或者没有找到匹配的选项，则默认查询 this.dataSourceForm[model]
      return formItem.options.find((item) => item.value === this.dataSourceForm[model]).label;
    },
  },
};
</script>

<style lang="scss" scoped></style>
